#ifndef ENEMY_H
#define ENEMY_H

#include "../sprite_handler.h"
#include "../input.h"
#include "../scrolling.h"
#include "player.h"
#include "../velocity.h"
#include "../collision.h"


////////////////////////////////////////////////////////////
// global variables
////////////////////////////////////////////////////////////

// turret Data
typedef struct STRUCT_ENEMY_DATA
{	
	int map_position_x, map_position_y;
	int ortho_wait_before_move;
	int dir_x, dir_y;
	int wait_x, wait_y;
	int milliseconds_since_last_move_x, milliseconds_since_last_move_y;
	int level;
	
} EnemyData;


////////////////////////////////////////////////////////////
// function prototypes
////////////////////////////////////////////////////////////
void NewEnemy(int, SpriteDimensions, int, int, int, int);
void EnemyUpdateFunction( SpriteHandler * );
void MoveEnemy(SpriteHandler *);
void SetEnemyAngle(SpriteHandler *);
void SetEnemyDirX(SpriteHandler *);
void SetEnemyDirY(SpriteHandler *);
int GetPlayerMapPosX(void);
int GetPlayerMapPosY(void);


// wait_before_move determines the enemy's speed: larger number = slower enemy
void NewEnemy( int frame_index, SpriteDimensions size, int pos_x, int pos_y, int wait_before_move, int level )
{
	SpriteHandler * enemy = newSpriteHandler();
	
	enemy->characterType = CHAR_ENEMY;
	
	EnemyData * enemy_data = malloc( sizeof( EnemyData ) );	
	memset( enemy_data, 0, sizeof( EnemyData ) );
	
	enemy->userData = enemy_data;
	enemy->_imageIndex = frame_index;
	enemy->size = size;
	enemy->x = 0;
	enemy->y = 0;
	
	enemy_data->map_position_x = pos_x;
	enemy_data->map_position_y = pos_y;
	
	enemy_data->ortho_wait_before_move = wait_before_move;
	
	enemy_data->wait_x = 999;
	enemy_data->wait_y = 999;
	
	enemy_data->dir_x = 0;
	enemy_data->dir_y = -1;
	
	enemy_data->milliseconds_since_last_move_x = 0;
	enemy_data->milliseconds_since_last_move_y = 0;
	
	enemy_data->level = level;
	
	// Based off frame index, we will set the idle animation
	AnimationInfo anim;
	
	anim.updatesPerFrame = 20;
	anim.numFrames = 2;
	anim.looping = TRUE;
	anim.flip = FLIP_NONE;
	
	switch ( frame_index )
	{
		case FRAME_ENEMY_8x8_1:
		{
			anim.frames[ 0 ] = FRAME_ENEMY_8x8_1;
			anim.frames[ 1 ] = FRAME_ENEMY_8x8_2;
			break;
		}
		case FRAME_ENEMY_16x16_PURPLE_1:
		{
			anim.frames[ 0 ] = FRAME_ENEMY_16x16_PURPLE_1;
			anim.frames[ 1 ] = FRAME_ENEMY_16x16_PURPLE_2;
			break;
		}
		case FRAME_ENEMY_16x16_BLUE_1:
		{
			anim.frames[ 0 ] = FRAME_ENEMY_16x16_BLUE_1;
			anim.frames[ 1 ] = FRAME_ENEMY_16x16_BLUE_2;
			break;
		}
		case FRAME_BOSS_1:
		{
			anim.frames[ 0 ] = FRAME_BOSS_1;
			anim.frames[ 1 ] = FRAME_BOSS_2;
			break;
		}
	}
	
	AddSpriteAnimation( enemy, 0, anim );
	SetSpriteAnimation( enemy, 0 );
	
	updateSpriteAttributes( enemy );
}


// turret Update Function

void EnemyUpdateFunction( SpriteHandler * sprite_handler )
{
    EnemyData * enemy_data = sprite_handler->userData;

	if ( sprite_handler->userData == NULL ) {
		return;
	}
	
	SetEnemyAngle(sprite_handler);
	SetEnemyDirX(sprite_handler);
	SetEnemyDirY(sprite_handler);
	
	enemy_data->wait_x = GetTimeToWaitBeforeMoveX(enemy_data->ortho_wait_before_move, sprite_handler->angle);
    enemy_data->wait_y = GetTimeToWaitBeforeMoveY(enemy_data->ortho_wait_before_move, sprite_handler->angle);

	MoveEnemy(sprite_handler);
	
	enemy_data->milliseconds_since_last_move_x += getElapsedTime();
    enemy_data->milliseconds_since_last_move_y += getElapsedTime();
	
	// Update the Sprite Attributes to reflect the changes we make in sprite_handler
	// Update animation
	UpdateSpriteAnimation( sprite_handler );
	updateSpriteAttributes( sprite_handler );
}


void MoveEnemy(SpriteHandler * sprite_handler)
{
    // TODO: bounds checking

    EnemyData * enemy_data = sprite_handler->userData;

    if (enemy_data->milliseconds_since_last_move_x > enemy_data->wait_x) {
        CharacterType collision_char_type = hasCollision(enemy_data->map_position_x + enemy_data->dir_x, enemy_data->map_position_y);
        
        if (collision_char_type != CHAR_ENEMY) {
            enemy_data->milliseconds_since_last_move_x = 0;
            enemy_data->map_position_x = enemy_data->map_position_x + enemy_data->dir_x;
        }
    }

    if (enemy_data->milliseconds_since_last_move_y > enemy_data->wait_y) {
        CharacterType collision_char_type = hasCollision(enemy_data->map_position_x, enemy_data->map_position_y + enemy_data->dir_y);
        
        if (collision_char_type != CHAR_ENEMY) {
            enemy_data->milliseconds_since_last_move_y = 0;
            enemy_data->map_position_y = enemy_data->map_position_y + enemy_data->dir_y;
        }
    }
}


////////////////////////////////////////////////////////////
// Function: SetTurretAngle
// ...
////////////////////////////////////////////////////////////
void SetEnemyAngle(SpriteHandler * sprite_handler)
{
    EnemyData * enemy_data = sprite_handler->userData;

    int x_diff =  GetPlayerMapPosX() - enemy_data->map_position_x;
    int y_diff =  GetPlayerMapPosY() - enemy_data->map_position_y;
    int angle = 0;
    int abs_x_diff = x_diff;
    int abs_y_diff = y_diff;

    if (abs_x_diff < 0) {
        abs_x_diff *= -1;
    }
    if (abs_y_diff < 0) {
        abs_y_diff *= -1;
    }

    if (x_diff == 0) {
        if (y_diff > 0) {
            angle = 180;
        }
        else if (y_diff < 0) {
            angle = 0;
        }
    }
    else if (x_diff > 0) {
        if (y_diff < 0) {
            if (abs_x_diff <= abs_y_diff) {
                angle = 30;
            }
            else if (abs_x_diff > abs_y_diff) {
                angle = 60;
            }
        }
        else if (y_diff == 0) {
            angle = 90;
        }
        else if (y_diff > 0) {
            if (abs_x_diff >= abs_y_diff) {
                angle = 120;
            }
            else if (abs_x_diff < abs_y_diff) {
                angle = 150;
            }
        }
    }
    else if (x_diff < 0) {
        if (y_diff > 0) {
            if (abs_x_diff <= abs_y_diff) {
                angle = 210;
            }
            else if (abs_x_diff > abs_y_diff) {
                angle = 240;
            }
        }
        else if (y_diff == 0) {
            angle = 270;
        }
        else if (y_diff > 0) {
            if (abs_x_diff >= abs_y_diff) {
                angle = 300;
            }
            else if (abs_x_diff < abs_y_diff) {
                angle = 330;
            }
        }
    }

    sprite_handler->angle = angle;
}


////////////////////////////////////////////////////////////
// Function: SetTurretDirX
// ...
////////////////////////////////////////////////////////////
void SetEnemyDirX(SpriteHandler * sprite_handler)
{
    int angle = sprite_handler->angle;
    int dir_x = 0;

    if (angle == 0 || angle == 180) {
        dir_x = 0;
    }
    else if (angle > 0 && angle < 180) {
        dir_x = 1;
    }
    else if (angle > 180 && angle < 360) {
        dir_x = -1;
    }

    EnemyData * enemy_data = sprite_handler->userData;
    enemy_data->dir_x = dir_x;
}


////////////////////////////////////////////////////////////
// Function: SetTurretDirY
// ...
////////////////////////////////////////////////////////////
void SetEnemyDirY(SpriteHandler * sprite_handler)
{
    int angle = sprite_handler->angle;
    int dir_y = 0;

    if (angle == 90 || angle == 270) {
        dir_y = 0;
    }
    else if ((angle > 270 && angle < 360) || (angle > 0 && angle < 90) || angle == 0) {
        dir_y = -1;
    }
    else if (angle > 90 && angle < 270) {
        dir_y = 1;
    }

    EnemyData * enemy_data = sprite_handler->userData;
    enemy_data->dir_y = dir_y;
}

#endif
